#!/usr/bin/env python

import pygtk
pygtk.require('2.0')
import gtk, gobject
import time, sys, os

import preferencesdialog, firstrundialog, profiledialog
import common, profile 

class Phennui:

    def pr(self, b): 
        print str(b)
   
    # The toggle_* functions are used to update the config when an setting is changed through the 'View' menu.
    def toggle_column(self, menuitem):

        name = menuitem.get_name()[26:]
        
        # Save the new column shown values.
        for pos, (key, value) in enumerate(self.prefs.config.columns):
            if key == name:
                self.prefs.config.columns[pos] = (key, menuitem.get_active())
        self.prefs.save_config()
        self.reload_columns()
        
    def toggle_groupby(self, menuitem):
    
        if not menuitem.get_active():
            return
        
        name = menuitem.get_name()[26:]
        self.prefs.config.groupby = name
        self.prefs.save_config()
        self.reload_profiles()
        
    # This function is used to update the config when the columns are reordered.
    def reorder_columns(self):
        
        columns = self.treeview.get_columns()
        
        if len(columns) != len(common.columns):
            return
        
        # Save the new column order.
        for i, column in enumerate(columns):
            self.prefs.config.columns[i] = (column.get_title().lower(), column.get_visible())
        self.prefs.save_config()
        self.reload_profiles()
        
        
    # The reload_* functions are used to reload stuff and make sure all changes get applied correctly.        
    def reload_prefs(self):
        
        # Update the checkboxes of the columns.
        for name, value in self.prefs.config.columns:
            self.ui.get_object('main_menubar_view_columns_' + name).set_active(value)
                
        # Update the groupby selector.
        if self.prefs.config.groupby in common.groupby_cols:
            self.ui.get_object('main_menubar_view_groupby_' + self.prefs.config.groupby).set_active(True)
        else:
            self.ui.get_object('main_menubar_view_groupby_none').set_active(True)
                            
        self.reload_profiles()
            
    def reload_profiles(self):
    
        if not hasattr(self, 'profiles'):
            self.profiles = self.ui.get_object('profilelist')
        
        if not hasattr(self, 'profilelist'):
            self.profilelist = profile.Profiles(self.prefs.config)
        
        # Store info about the current selection to restore it later.
        selected = self.get_selected_profile()
        
        # Clear the profiles list.
        self.profiles.clear()
        
        self.groups = {}
        for prof in self.profilelist:
            
            # If grouped by something.
            if self.prefs.config.groupby in common.columns_mapping:
                groupname = prof
                for name in common.columns_mapping[self.prefs.config.groupby].split('.'):
                    groupname = getattr(groupname, name)
                if groupname not in self.groups:
                    data = [None, None, None, None, None, None, None]
                    data[common.columns.index(self.treeview.get_expander_column().get_title().lower()) + 1] = groupname
                    self.groups[groupname] = self.profiles.append(None, data)
                prof.row = self.profiles.append(self.groups[groupname], [prof, prof.name, prof.data.host, prof.data.nick, prof.data.owner, prof.state, common.colors[prof.state.lower()]])
            
            # If not grouped at all.
            else:
                prof.row = self.profiles.append(None, [prof, prof.name, prof.data.host, prof.data.nick, prof.data.owner, prof.state, common.colors[prof.state.lower()]])
                
            if prof == selected:
                self.treeview.expand_to_path(self.profiles.get_path(prof.row))
                self.treeview.get_selection().select_iter(prof.row)
                
        self.reload_buttons()
                
    def reload_columns(self):
        
        columns = self.treeview.get_columns()
        for column, (name, shown) in zip(columns, self.prefs.config.columns):
            column.set_attributes(column.get_cell_renderers()[0], text = common.columns.index(name) + 1, background = 6)
            column.set_title(name.capitalize())
            column.set_visible(shown)
            
    def reload_buttons(self):
        
        def set_sensitive(name, sensitive):
            self.ui.get_object('main_menubar_file_' + name).set_sensitive(sensitive)
            self.ui.get_object('main_toolbar_' + name).set_sensitive(sensitive)
        
        profile = self.get_selected_profile()
        
        if not profile:
            set_sensitive('remove', False)
            set_sensitive('edit', False)
            set_sensitive('start', False)
            set_sensitive('stop', False)
            set_sensitive('show', False)
            set_sensitive('hide', False)
        else:
            running = profile.running()
            set_sensitive('remove', True)
            set_sensitive('edit', True)
            set_sensitive('start', not running)
            set_sensitive('stop', running)
            set_sensitive('show', running and not profile.shown)
            set_sensitive('hide', running and profile.shown)

            
    # Function used to get the selected profile.
    def get_selected_profile(self):
        
        (model, iter) = self.treeview.get_selection().get_selected()
        
        if not iter:
            return None
        return model.get(iter, 0)[0]
        

    def __init__(self):
        
        # Load the gui.
        self.ui = gtk.Builder()
        self.ui.add_from_file('phennui.glade') 
        
        # Used to keep the shown/hidden state stored.
        self.shown = True
        
        # Create the firstrun dialog.
        if not os.access('config.py', os.R_OK|os.W_OK):
            preferencesdialog.preferencesdialog.create_default_config()
            self.firstrun = firstrundialog.firstrundialog(self.ui)
            self.firstrun.run()  
        else:
            self.firstrun = firstrundialog.firstrundialog(self.ui)
        
        # Create the preferences dialog.
        self.prefs = preferencesdialog.preferencesdialog(self.ui)      
        
        # Create the profile dialog.
        self.profiledialog = profiledialog.profiledialog(self.ui)  

        # Add the columns to the tree view.
        def column(name, pos):
            col = gtk.TreeViewColumn(name, gtk.CellRendererText(), text = pos, background = 6)
            col.set_resizable(True)
            col.set_reorderable(True)
            col.set_sort_column_id(pos)
            return col
        
        self.treeview = self.ui.get_object('main_treeview')
        self.treeview.append_column(column('Name', 1))
        self.treeview.append_column(column('Server', 2))
        self.treeview.append_column(column('Nickname', 3))
        self.treeview.append_column(column('Owner', 4))
        self.treeview.append_column(column('State', 6))
        
        # Load the preferences into the main window.
        self.reload_prefs()  
        
        # Show/hide the columns, and change their order.
        self.reload_columns()
        
        # Load the profiles into the main profile list.
        self.reload_profiles()   
        
        # Load the license into the about dialog.
        try:
            f = open('LICENSE', 'r+')
            self.ui.get_object('aboutdialog').set_license(f.read())
            f.close()
        except IOError, e:
            print >> sys.stderr, 'Error: LICENSE file could not be read: ', e
            self.ui.get_object('aboutdialog').set_license(
                str(self.ui.get_object('aboutdialog').get_license()) + str(e))
                
        # Check if vte is available, else disable show/hide.
        try:
            import vte
        except:
            print >> sys.stderr, 'Warning: You need to have vte installed to display the phenny terminals. The program will still run, but you won\'t be able to view the terminal output of the phennies.'
            self.ui.get_object('main_toolbar_sep3').hide()
            self.ui.get_object('main_toolbar_show').hide()
            self.ui.get_object('main_toolbar_hide').hide()
            self.ui.get_object('preferencesdialog_display_terminals').hide()
                
        # Bind the functions.
        self.ui.connect_signals({
            # Global events.
            'event_quit':                   lambda f, g = None:             gtk.main_quit(),
            
            # Icon related events.
            'icon_menu':                    lambda icon, button, time:      self.ui.get_object('statusicon_menu').popup(None, None, gtk.status_icon_position_menu, button, time, icon),
            
            # Main window related events.
            'main_close':                   self.ui.get_object('main').hide_on_delete,
            'main_showhide':                lambda f:                       self.shown and (self.ui.get_object('main').hide() or True) or self.ui.get_object('main').show(),
            'main_state':                   lambda f, g = None:             setattr(self, 'shown', not ((g.changed_mask & gtk.gdk.WINDOW_STATE_WITHDRAWN) and (g.new_window_state & gtk.gdk.WINDOW_STATE_WITHDRAWN))),
            'main_columns_changed':         lambda f:                       [self.reorder_columns(), self.prefs.save_config()],
            'profile_selected':             lambda f:                       self.reload_buttons(),
            
            # About dialog related events.
            'about_open':                   lambda f:                       self.ui.get_object('aboutdialog').run(),
            'about_close':                  lambda f, g:                    self.ui.get_object('aboutdialog').hide(),
            
            # Preferences dialog related events.
            'prefs_open':                   lambda f:                       self.prefs.run(),
            'prefs_response':               lambda f, g:                    [self.prefs.event_response(f, g), self.reload_prefs()],
            'prefs_toggle_column':          self.toggle_column,
            'prefs_change_groupby':         self.toggle_groupby,
            
            # Profile dialog related events.
            'profile_response':             lambda f, g:                    [self.profiledialog.event_response(f, g), self.reload_profiles()],
            'profile_add':                  lambda f:                       [self.profilelist.append(profile.Profile.new()), self.reload_profiles()],
            'profile_remove':               lambda f:                       [self.get_selected_profile() and self.get_selected_profile().__del__(), self.profilelist.remove(self.get_selected_profile()), self.reload_profiles()],
            'profile_edit':                 lambda f:                       self.get_selected_profile() and self.profiledialog.run(self.get_selected_profile()),
            
            # Profile related events.
            'profile_start':                lambda f:                       self.get_selected_profile() and [self.get_selected_profile().start(), self.reload_profiles(), self.reload_buttons()],
            'profile_stop':                 lambda f:                       self.get_selected_profile() and [self.get_selected_profile().stop(), self.reload_profiles(), self.reload_buttons()],
            'profile_show':                 lambda f:                       self.get_selected_profile() and [self.get_selected_profile().show(), self.reload_buttons()],
            'profile_hide':                 lambda f:                       self.get_selected_profile() and [self.get_selected_profile().hide(), self.reload_buttons()],
            
            # First run dialog related events.
            'firstrun_apply':               self.firstrun.event_apply,
            'firstrun_cancel':              self.firstrun.event_cancel,
            'firstrun_close':               self.firstrun.event_close,
            'firstrun_prepare':             self.firstrun.event_prepare, 
            'firstrun_checkpage':           self.firstrun.check_page,           
        })
        
    def main(self):
        
        # Start main loop.
        gtk.main()
        
if __name__ == '__main__':
    ph = Phennui()
    ph.main()
